#pragma once

#include "Iteracion.h"
#include "Puntero.h"

#define foreach(item, iterador)																			\
	for (auto item##_iterator = wrapIterator(iterador); item##_iterator.C; item##_iterator.C = false)	\
		for (auto item = item##_iterator.D; item##_iterator.I.HayElemento() ? &(item = *item##_iterator.I) || true : false; item##_iterator.I.Avanzar())

template <class T>
class Iterador
{
public:
	Iterador(Iteracion<T>* iteracion = NULL);
	Iterador(const Puntero<Iteracion<T>>& iteracion);
	Iterador(const Iterador<T>& iterador);

	const Iterador<T>& operator=(Iteracion<T>* iteracion);
	const Iterador<T>& operator=(const Puntero<Iteracion<T>>& iteracion);
	const Iterador<T>& operator=(const Iterador<T>& iterador);

	void Reiniciar();
	bool HayElemento() const;
	const T& ElementoActual() const;
	void Avanzar();

	inline Iterador<T>& operator++();
	inline Iterador<T>& operator++(int);
	inline const T& operator*() const;

	template <class U> operator Iterador<U>() const;

	template <class U, typename Conv>
	Iterador<U> Convert() const;

private:
	Puntero<Iteracion<T>> m_Iteracion;
};

template <class T>
struct IteradorWrapper
{
private:
	void Init(const Iterador<T>& it)
	{
		I = it;
		I.Reiniciar();
		C = true;
	}

public:
	Iterador<T> I;
	bool C;
	T D;

	IteradorWrapper(const Iterador<T>& it)
	{
		Init(it);
	}
};

template <class T>
IteradorWrapper<T> wrapIterator(const Iterador<T>& it)
{
	return IteradorWrapper<T>(it);
}

#include "Iterador.cpp"